package roboSoccer;

/**
 * The RoboPlayer class represents the physical characteristics of a robot as
 * well as other facts about the robot's state. It holds the Control object that
 * connects with the robot, and also the player behavior that tells Control what
 * to do.
 * <p>
 * As an extension of FieldObject, this class is updated like a FieldObject for
 * its position, but it also contains an update method which takes a player
 * behavior and the current game state. The behavior is executed in this update
 * method, where commands are sent to the physical robot.
 * 
 * @author Ben Hopkins
 */
public class RoboPlayer extends FieldObject {

	/**
	 * How large to draw the robot in pixels.
	 */
	public static final int sizeRadius = 9;
	/**
	 * How close is safe to pass by other robots.
	 */
	public static float passByLength = 10;
	/**
	 * How many degrees the direction indicator will cover when drawing the
	 * robot.
	 */
	public static final int drawDirWidth = 20; // width of the direction
	// indicator, degrees

	/**
	 * A pointer to the team this player is on.
	 */
	public RoboTeam team;

	/**
	 * The ID number of the player on the team.
	 */
	public int id;

	/**
	 * The PlayerBehavior which dictates what the robot will do when update is
	 * called.
	 */
	public PlayerBehavior behavior;
	
	/**
	 * This player has been assigned a behavior already this turn.
	 */
	public boolean behaviorAssigned;
	
	/**
	 * Most recent distance to the ball.
	 */
	public float ballDistance;
	
	/**
	 * The Control object which interfaces with the PlayerBehavior to send
	 * commands to the physical robot.
	 */
	public Control controller;

	/**
	 * Constructor initializes values, setting team number and ID on the team.
	 * 
	 * @param team
	 *            The team number that this robot is on.
	 * @param id
	 *            The ID number of this robot on the team.
	 */
	public RoboPlayer(RoboTeam team, int id) {
		super();
		this.team = team;
		this.id = id;
		position.direction = 0;
		position.x = position.x + 100 * team.teamNumber;
		position.y = position.y + sizeRadius * 3 * id;

		if( behavior == null )
			behavior = new PbDefault(this);
		if( controller == null )
			controller = new ControlNull();
	}
	
	/**
	 * This method sets the controller to move the robot in a simulated game.
	 * 
	 * @param sim The simulated game which has the simulated robot object within it.
	 */
	public void setSimulatedControl(SimulationHandler sim)
	{
		controller = new ControlSimulation(sim.objects[id+(5*team.teamNumber)]);
	}
	
	/**
	 * Sets the controller to control an NXT robot
	 */
	public void setNXTControl()
	{
		controller = new ControlNXT(id);
	}

	/**
	 * Executes the player behavior according to the current game state.
	 * 
	 * @param pb
	 *            A new player behavior object is passed every time. If this is
	 *            found to be different from the current player behavior, it
	 *            replaces the old one.
	 * @param game
	 *            The current game state gives the behavior all the information
	 *            it needs.
	 */
	public void update(PlayerBehavior pb, GameState game) {
		// Player behaviors are identified by their names, arguments in
		// behaviors should be
		// represented in the name string so the same behavior with different
		// arguments will
		// replace the old one.
		if (pb != null && !pb.name.equals(behavior.name))
			behavior = pb;
		
		behaviorAssigned = true;

		// Only do the behavior if the controller successfully initialized.
		if (controller != null && controller.functioning)
			behavior.update(game);
	}

}
